/*
 * Copyright (c)  2015~2020, xforceplus
 * All rights reserved.
 * Project:datacare-orm
 * Id: DSTransactionManager.java   2020-10-05 14-18-28
 * Author: Evan
 */
package cn.datacare.orm.connection;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * Title:
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: 2015~2020
 * </p>
 * <p>
 * Company/Department: xforceplus
 * </p>
 *
 * @author Evan
 * <b>Creation Time:</b> 2020-10-05 14-18-28
 * @since V1.0
 */
public class DSTransactionManager {

    static ThreadLocal<Boolean> inTrans = ThreadLocal.withInitial(() -> false);

    static ThreadLocal<Map<DataSource, Connection>> cons = new ThreadLocal<>();

    public static void start() {
        inTrans.set(true);
    }

    public static void commit() throws SQLException {
        Map<DataSource, Connection> map = cons.get();
        try {
            if (map == null) {
                return;
            }
            SQLException e = null;
            for (Connection conn : map.values()) {
                try {
                    conn.commit();

                } catch (SQLException ex) {
                    e = ex;
                } finally {
                    try {
                        conn.close();
                    } catch (SQLException ex) {
                        System.err.println("commit error of connection " + conn + " " + ex.getMessage());
                    }

                }

            }
            if (e != null) {
                throw e;
            }
        } finally {
            clear();
        }


    }

    public static void rollback() throws SQLException {
        Map<DataSource, Connection> map = cons.get();
        SQLException e = null;
        if (map == null) {
            return;
        }
        try {
            for (Connection conn : map.values()) {
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    e = ex;
                } finally {
                    try {
                        conn.close();
                    } catch (SQLException ex) {
                        // TODO Auto-generated catch block
                        ex.printStackTrace();
                    }

                }

            }
            if (e != null) {
                throw e;
            }
        } finally {
            clear();
        }


    }

    public static void clear() {
        cons.remove();
        inTrans.remove();
    }

    public static Connection getCurrentThreadConnection(DataSource ds) throws SQLException {
        Map<DataSource, Connection> map = cons.get();
        Connection conn = null;
        if (map == null) {
            map = new HashMap<>(16);
            conn = ds.getConnection();
            //如果用户还有不需要事物，且每次都提交的操作，这个需求很怪，不管了
            conn.setAutoCommit(false);
            map.put(ds, conn);
            cons.set(map);
            return conn;
        }
        conn = map.get(ds);
        if (conn != null) {
            return conn;
        }
        conn = ds.getConnection();
        conn.setAutoCommit(false);
        map.put(ds, conn);

        return conn;

    }

    public static boolean inTrans() {
        return inTrans.get();
    }

}
